// by mircemk Mar.2026 #include TM1638lite module(4, 3, 2); #define W_CLK 8 #define FQ_UD 9 #define DATA 10 #define RESET 11 #define ENC_A A0 #define ENC_B A1 #define ENC_SW A2 // Копчето на енкодерот unsigned long freq = 7000000; unsigned long steps[] = {10, 100, 1000, 10000, 100000, 1000000}; int stepIndex = 2; const char* modes[] = {"A ", "USB ", "LSB "}; int modeIndex = 0; long offset = 0; bool offsetActive = false; // Brightness контроли int brightnessPercent = 50; // Почетна на 50% bool brightnessMode = false; unsigned long tempDisplayTimer = 0; bool showingTemp = false; const byte segmentMap[] = { 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F }; void setup() { pinMode(W_CLK, OUTPUT); pinMode(FQ_UD, OUTPUT); pinMode(DATA, OUTPUT); pinMode(RESET, OUTPUT); pinMode(ENC_A, INPUT_PULLUP); pinMode(ENC_B, INPUT_PULLUP); pinMode(ENC_SW, INPUT_PULLUP); ad9850_reset(); updateDDS(freq + offset); setBrightnessLevel(brightnessPercent); updateMainDisplay(); } void loop() { // Читање на копчето на енкодерот (A3) if (digitalRead(ENC_SW) == LOW) { brightnessMode = !brightnessMode; if (brightnessMode) showTempMsg("BRIGHT "); else updateMainDisplay(); delay(300); // Debounce } uint8_t buttons = module.readButtons(); // Додека сме во Brightness Mode, другите тастери се деактивирани if (!brightnessMode) { if (buttons == 1) { stepIndex = (stepIndex + 1) % 6; char buffer[9]; sprintf(buffer, "S%7ld", steps[stepIndex]); showTempMsg(buffer); while(module.readButtons() == 1); } if (buttons == 2) { modeIndex = (modeIndex + 1) % 3; showTempMsg(modes[modeIndex]); while(module.readButtons() == 2); } if (buttons == 4) setBand(1800000, 2); if (buttons == 8) setBand(3500000, 3); if (buttons == 16) setBand(7000000, 4); if (buttons == 32) setBand(14000000, 5); if (buttons == 64) setBand(21000000, 6); if (buttons == 128) { offsetActive = !offsetActive; offset = offsetActive ? 455000 : 0; showTempMsg(offsetActive ? "_455_ " : "OFF "); module.setLED(7, offsetActive ? 1 : 0); updateDDS(freq + offset); while(module.readButtons() == 128); } } // Енкодер логика (за Фреквенција или за Brightness) static int lastA = HIGH; int currentA = digitalRead(ENC_A); if (currentA != lastA && currentA == LOW) { if (brightnessMode) { // Менување на осветленост (чекор по 10%) if (digitalRead(ENC_B) == LOW) brightnessPercent -= 10; else brightnessPercent += 10; brightnessPercent = constrain(brightnessPercent, 0, 100); setBrightnessLevel(brightnessPercent); char brBuf[9]; sprintf(brBuf, "BR %3d ", brightnessPercent); module.displayText(brBuf); } else { // Стандардна фреквенција if (digitalRead(ENC_B) == LOW) freq -= steps[stepIndex]; else freq += steps[stepIndex]; freq = constrain(freq, 0, 49999999); updateDDS(freq + offset); if (!showingTemp) updateMainDisplay(); } } lastA = currentA; if (showingTemp && (millis() > tempDisplayTimer) && !brightnessMode) { showingTemp = false; updateMainDisplay(); } } void showTempMsg(const char* msg) { module.displayText(msg); tempDisplayTimer = millis() + 1000; showingTemp = true; } void setBrightnessLevel(int percent) { // TM1638 користи 0x88 (минимум) до 0x8F (максимум) за осветленост byte level = map(percent, 0, 100, 0, 7); digitalWrite(4, LOW); // STB shiftOut(2, 3, LSBFIRST, 0x88 + level); digitalWrite(4, HIGH); // STB } void updateMainDisplay() { unsigned long tempFreq = freq; for (int i = 7; i >= 0; i--) { byte segs = 0; if (tempFreq > 0 || i == 7) { segs = segmentMap[tempFreq % 10]; tempFreq /= 10; } else { segs = 0x00; } if (i == 1 || i == 4) segs |= 0x80; sendRawData(i, segs); } } void sendRawData(byte position, byte data) { digitalWrite(4, LOW); shiftOut(2, 3, LSBFIRST, 0xC0 + (position * 2)); shiftOut(2, 3, LSBFIRST, data); digitalWrite(4, HIGH); } void setBand(unsigned long f, int ledIndex) { freq = f; for (int i = 0; i < 7; i++) module.setLED(i, 0); module.setLED(ledIndex, 1); updateDDS(freq + offset); updateMainDisplay(); } void ad9850_reset() { digitalWrite(W_CLK, LOW); digitalWrite(FQ_UD, LOW); digitalWrite(RESET, LOW); digitalWrite(RESET, HIGH); digitalWrite(RESET, LOW); } void updateDDS(unsigned long f) { unsigned long tuning_word = f * 4294967296ULL / 125000000; for (int i = 0; i < 32; i++) { digitalWrite(DATA, tuning_word & 0x01); digitalWrite(W_CLK, HIGH); digitalWrite(W_CLK, LOW); tuning_word >>= 1; } for (int i = 0; i < 8; i++) { digitalWrite(DATA, LOW); digitalWrite(W_CLK, HIGH); digitalWrite(W_CLK, LOW); } digitalWrite(FQ_UD, HIGH); digitalWrite(FQ_UD, LOW); }